#pragma once
#include <jsoncpp/json/json.h>
#include <string>
#include <memory>
#include <sstream>

//消息种类
enum chat_msg_type {
  Register = 0,  //注册
  Register_Resp,
  Login,          //登录
  Login_Resp,
  AddFriend,      //添加好友
  AddFriend_Resp,
  SendMsg,        //发送消息
  SendMsg_Resp,
  PushMsg,        //推送消息
  PushMsg_Resp,
  PushAddFriendMsg,//推送添加好友请求消息
  PushAddFriendMsg_Resp,
  GetFriendMsg,   //获取全部好友
  GetFriendMsg_Resp

};

//应答消息种类
enum reply_status {
  REGISTER_SUCCESS = 0,    //注册成功
  REGISTER_FAILED,
  LOGIN_SUCCESS,           //登录成功
  LOGIN_FAILED,
  ADDFRIEND_SUCCESS,       //添加好友成功
  ADDFRIEND_FAILED,
  SENDMSG_SUCCESS,         //发送消息成功
  SENDMAS_FAILED,
  GETFRIEND_SUNCCESS,      //获取好友列表成功
  GETFRIEND_FAILED
};

/*注册请求的消息格式
 *  sockfd_ 消息到达服务端之后,由服务端自己带上sockfd_
 *  msg_type_ : Register
 *  json_msg {
 *    nickname : "xxx"
 *    ...
 *  }
 *
 *注册的应答
 *  msg_type_ : Register_Resp
 *  reply_status : REGISTER_SUCCESS | REGISTER_FAILED
 *  
 *登录的消息格式
 *  sockfd_
 *  msg_type_ : Login
 *  json_msg {
 *  telnum : "xxx"
 *  passwd : "xxx"
 *  }
 * 
 *
 *   登录的应答：
 *   msg_type : Login_Resp;
 *   reply_status_ : LOGIN_SUCCESS/LOGIN_FAILED
 *       如果是LOGIN_SUCCESS : [user_id_]
 *
 *
 *
 * 添加好友请求：
 *    msg_type_ : AddFriend
 *    json_msg_ :{
 *      fri_tel_num : xxxx
 *    }
 *
 *
 *  推送添加好友的请求
 *      msg_type : PushAddFriendMsg
 *      sockfd_ : 被添加方的套接字描述符
 *      json_msg_: {
 *          adder_nickname : xxx
 *          adder_school : xxx
 *          adder_userid : xxx
 *      }
 *
 * 推送添加好友的应答（被添加方发送给服务端的）
 *     msg_type : PushAddFriendMsg_Resp
 *     user_id : 被添加方的id
 *     reply_status : ADDFRIEND_SUCCESS / ADDFRIEND_FAILED
 *         如果说是ADDFRIEND_SUCCESS
 *             json_msg_ : 添加方的id
 *
 *  添加好友的应答：
 *      msg_type: AddFriend_Resp
 *      reply_status : ADDFRIEND_FAILED / ADDFRIEND_SUCCESS
 *          如果是成功：ADDFRIEND_SUCCESS
 *             json_msg_ : 
 *                 BeAdd_nickname : 被添加方的名字
 *                 BeAdd_school ： 被添加方的学校
 *                 BeAdd_userid : 被添加方的id
 * */

class JsonUtil{
    public:
        static bool Serialize(const Json::Value& value, std::string* body) {
            Json::StreamWriterBuilder swb;
            std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
        
            std::stringstream ss;
            int ret = sw->write(value, &ss);
            if (ret != 0) {
                return false;
            }
            *body = ss.str();
            return true;
        }
        
        static bool UnSerialize(const std::string& body, Json::Value* value) {
            Json::CharReaderBuilder crb;
            std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
        
            std::string err;
            bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), value, &err);
            if (ret == false) {                                                                                                                                                                  
                return false;
            }
            return true;
        }
};
class ChatMsg {
public:
  ChatMsg() {
    sockfd_ = -1;
    msg_type_ = -1;
    userid_ = -1;
    reply_status_ = -1;
    json_msg_.clear();
  }

  ~ChatMsg() {

  }

  //反序列化
  int PraseChatMsg(int sockfd, const std::string& msg) {
    //调用json的反序列化接口
    Json::Value temp;
    bool ret = JsonUtil::UnSerialize(msg, &temp);
    if (ret == false) {
      return -1;
    }
    //Json::Reader Reader;
    //Json::Value temp;
    //Reader.parse(msg, temp);
    //赋值给成员变量
    sockfd_ = sockfd;
    msg_type_ = temp["msg_type"].asInt();
    userid_ = temp["user_id"].asInt();
    reply_status_ = temp["reply_status"].asInt();
    json_msg_ = temp["json_msg"];
    return 0;
  }

  //序列化
  bool GetMsg(std::string* msg) {
    Json::Value temp;
    temp["msg_type"] = msg_type_;
    temp["user_id"] = userid_;
    temp["reply_status"] = reply_status_;
    temp["json_msg"] = json_msg_;
    return JsonUtil::Serialize(temp, msg);
//    *msg = temp.toStyledString();
//    return true;
  }

  //获取value值
  std::string GetValue(const std::string& key) {
    if (!json_msg_.isMember(key)) {
      return "";
    }
    return json_msg_[key].asString();
  }

  //设置kv键值对
  void SetValue(const std::string& key, const std::string& value) {
    json_msg_[key] = value;
  }

  void SetValue(const std::string& key, int& value) {
    json_msg_[key] = value;
  }
  void clear() {
    msg_type_ = -1;
    userid_ = -1;
    reply_status_ = -1;
    json_msg_.clear();
  }
public:
  //文件描述符,表示是哪个客户端的操作
  int sockfd_;

  //消息类型
  int msg_type_;

  //用户id
  int userid_;
  //回答的类型
  int reply_status_;
  //json消息
  Json::Value json_msg_;
};
